#include "Camera.h"
#include "glm/gtc/matrix_transform.hpp"
#include <iostream>
#include "ActorBase.h"

namespace PotatoGTK
{
	Camera::Camera():m_position(0,0,0), m_upVector(0,1,0), m_rightVector(1,0,0), m_CameraProjectionType(CameraProjectionType::Perspective)
	{

	}

	Camera::~Camera()
	{

	}

	void Camera::SetPosition(const glm::vec3& position)
	{
		m_position = position;
	}

	const glm::vec3& Camera::GetPosition()
	{
		return m_position;
	}

	void Camera::SetUpVector(const glm::vec3& up)
	{
		m_upVector = up;
	}

	const glm::vec3& Camera::GetUpVector()
	{
		return m_upVector;
	}

	void Camera::SetRightVector(const glm::vec3& right)
	{
		m_rightVector = right;
	}
	const glm::vec3& Camera::GetRightVector()
	{
		return m_rightVector;
	}

	void Camera::SetCameraProjectionType(const CameraProjectionType& projectionType)
	{
		m_CameraProjectionType = projectionType;
	}

	void Camera::SetPlaneDis(const float& nearPlaneDis, const float& farPlaneDis)
	{
		if (nearPlaneDis < 0 || farPlaneDis < 0 || nearPlaneDis > farPlaneDis)
		{
			std::cout << "PlaneDis Value error!" << std::endl;
			return;
		}
		m_nearPlaneDis = nearPlaneDis;
		m_farPlaneDis = farPlaneDis;
	}

	void Camera::SetFovy(const float& fovy)
	{
		m_fovy = fovy;
	}

	void Camera::SetAspect(const float& aspect)
	{
		m_aspect = aspect;
	}

	void Camera::SetOrthoWidth(const float& orthoWidth)
	{
		m_orthoWidth = orthoWidth;
	}

	glm::mat4 Camera::GetVMatrix()
	{
		glm::vec3 frontVec = glm::cross(m_upVector, m_rightVector);
		glm::vec3 centerPoint = m_position + frontVec;

		return glm::lookAt(m_position, centerPoint, m_upVector);
	}

	glm::mat4 Camera::GetPMatrix()
	{
		if (CameraProjectionType::Perspective == m_CameraProjectionType)
		{
			return glm::perspective(glm::radians(m_fovy), m_aspect, m_nearPlaneDis, m_farPlaneDis);
		}
		else if (CameraProjectionType::Orthographic == m_CameraProjectionType)
		{
			return glm::ortho(-m_orthoWidth * 0.5, m_orthoWidth * 0.5, -m_aspect * m_orthoWidth * 0.5, m_aspect * m_orthoWidth * 0.5);
		}
		else
		{
			return glm::identity<glm::mat4>();
		}
	}
	void Camera::BeginRender()
	{

	}

	void Camera::Render(ActorBase* actor)
	{
		actor->Render(this->GetVMatrix(), this->GetPMatrix());
	}

	void Camera::EndRender()
	{

	}
}